﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using FileSystem.Models;
using FileSystem.Services.IServices;
using SQLite;

namespace FileSystem.Services.Realization {
    /// <summary>
    /// 目录项存储
    /// </summary>
    public class DirItemStorage : IDirItemStorage {
        // ******** 公开变量
        /// <summary>
        /// DirItemTable文件路径
        /// </summary>
        public static readonly string DbPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData), DbName);

        /// <summary>
        /// DirItemTable数据库连接
        /// </summary>
        private SQLiteAsyncConnection _connection;

        public SQLiteAsyncConnection Connection =>
            _connection ?? (_connection = new SQLiteAsyncConnection(DbPath));

        // ******** 私有变量
        /// <summary>
        /// TableDb文件名
        /// </summary>
        private const string DbName = "DirItemTable.sqlite3";

        /// <summary>
        /// 偏好存储服务
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        // ******** 继承方法
        /// <summary>
        /// 初始化目录项存储
        /// </summary>
        public async Task InitializeAsync() {
            // DirItemTable.sqlite3 文件初始化
            await Connection.CreateTableAsync<DirItem>();

            //将程序自带的管理员根目录写入表中,不用AddAsync,减少耦合度
            foreach (var user in UserConst.Users)
                await Connection.InsertAsync(new DirItem {
                    DirItemName = user.UserName + ":",
                    Identifier = "文件标识符",
                    DirItemType = DirItem.FolderConst,
                    Location = user.UserName + ":",
                    Size = 0,
                    FolderContent = null,
                    IsRootDirItem = true,
                    PhysicalBlockAddress = 0
                });

            _preferenceStorage.Set(DirItemStorageConstants.VersionKey,
                DirItemStorageConstants.Version);
        }

        /// <summary>
        /// 目录项存储是否已经初始化
        /// </summary>
        public bool IsInitialized() {
            return _preferenceStorage.Get(DirItemStorageConstants.VersionKey,
                    DirItemStorageConstants.DefaultVersion) ==
                DirItemStorageConstants.Version;
        }

        /// <summary>
        /// 增加目录项
        /// </summary>
        /// <param name="dirItem">要添加的目录项</param>
        public async Task AddAsync(DirItem dirItem) {
            await Connection.InsertAsync(dirItem);
        }

        /// <summary>
        /// 删除目录项
        /// </summary>
        /// <param name="dirItem">要删除的目录项</param>
        public async Task RemoveAsync(DirItem dirItem) {
            await Connection.DeleteAsync(dirItem);
        }

        /// <summary>
        /// 修改目录项的属性
        /// </summary>
        /// <param name="dirItem">目录项</param>
        /// <param name="property">要修改的属性</param>
        /// <param name="newContent">新的值</param>
        public async Task ModifyProperty(DirItem dirItem,
            DirItemConst.Property property, string newContent) {
            switch (property) {
                case DirItemConst.Property.DirItemName: {
                    dirItem.DirItemName = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
                case DirItemConst.Property.Identifier: {
                    dirItem.Identifier = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
                case DirItemConst.Property.DirItemType: {
                    dirItem.DirItemType = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
                case DirItemConst.Property.Location: {
                    dirItem.Location = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
                case DirItemConst.Property.FolderContent: {
                    dirItem.FolderContent = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
            }
        }

        /// <summary>
        /// 修改目录项的属性
        /// </summary>
        /// <param name="dirItem">目录项</param>
        /// <param name="property">要修改的属性</param>
        /// <param name="newContent">新的值</param>
        public async Task ModifyProperty(DirItem dirItem, DirItemConst.Property property, bool newContent) {
            switch (property)
            {
                case DirItemConst.Property.IsRootDirItem:
                {
                    dirItem.IsRootDirItem = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
            }
        }

        /// <summary>
        /// 修改目录项的属性
        /// </summary>
        /// <param name="dirItem">目录项</param>
        /// <param name="property">要修改的属性</param>
        /// <param name="newContent">新的值</param>
        public async Task ModifyProperty(DirItem dirItem,
            DirItemConst.Property property, int newContent) {
            switch (property) {
                case DirItemConst.Property.Size: {
                    dirItem.Size = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
                case DirItemConst.Property.PhysicalBlockAddress: {
                    dirItem.PhysicalBlockAddress = newContent;
                    await Connection.InsertOrReplaceAsync(dirItem);
                    break;
                }
            }
        }

        public async Task<DirItem> GetDirItemAsync(int id) {
            return await Connection.Table<DirItem>()
                .FirstOrDefaultAsync(p => p.Id == id);
        }

        /// <summary>
        /// 根据目录项名获得一个目录项
        /// </summary>
        /// <param name="location">路径</param>
        /// <param name="dirItemName">目录项名</param>
        public async Task<DirItem> GetDirItemAsync(string location,
            string dirItemName) {
            return await Connection.Table<DirItem>().FirstOrDefaultAsync(p =>
                p.Location == location && p.DirItemName == dirItemName);
        }

        /// <summary>   
        /// 获得某个路径下的所有目录项
        /// </summary>
        /// <param name="location">路径</param>
        public async Task<IList<DirItem>> GetDirItemsAsync(string location) {
            return await Connection.Table<DirItem>()
                .Where(p => p.Location == location).ToListAsync();
        }

        /// <summary>
        /// 判断目录项是否存在
        /// </summary>
        /// <param name="location">路径</param>
        /// <param name="dirItemName">目录项名</param>
        public async Task<bool> Exist(string location, string dirItemName) {
            var item = await Connection.Table<DirItem>()
                .FirstOrDefaultAsync(p =>
                    p.Location == location && p.DirItemName == dirItemName);
            if (item == null)
                return false;
            else
                return true;
        }

        // ******** 公开方法
        /// <summary>
        /// 目录项存储
        /// </summary>
        public DirItemStorage(IPreferenceStorage preferenceStorage) {
            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 关闭数据库
        /// </summary>
        public async Task CloseAsync() {
            await Connection.CloseAsync();
        }

        // ******** 私有方法
    }
}